//
//  PMRatchetJoint.m
//  PezMonkey
//
//  Created by Spence DiNicolantonio on 12/30/09.
//  Copyright 2009 Necrosoft. All rights reserved.
//

/**
 * A subclass of PMConstraint for representing ratchet joints. PMRatchetJoints
 * bind the rotation of two rigid bodies much like a socket wrench. A PMRatchetJoint
 * is defined with a phase angle, which is the initial angle offset between the 
 * two bound rigid bodies, and a ratchet angle, which is the angle between each 
 * ratchet. 
 */

#import "PMRatchetJoint.h"
#import "PMBody.h"


@implementation PMRatchetJoint


#pragma mark -
#pragma mark Init

/**
 * Returns a PMRatchetJoint object initialized to bind two given rigid bodies
 * with given phase and ratchet angles. 
 */
- (id)initWithBodyA:(PMBody *)aBody bodyB:(PMBody *)otherBody phase:(PMFloat)phase ratchet:(PMFloat)ratchet {
	if (![super init])
		return nil;
	
	// allocate and initialize cpConstraint
	constraint = cpRatchetJointNew(aBody.cpBody, otherBody.cpBody, phase, ratchet);
	
	// set body references
	self.bodyA = aBody;
	self.bodyB = otherBody;
	
	// reference this PMConstraint object with cpConstraint's data pointer
	// this is for internal use
	constraint->data = self;
	
	return self;
}


#pragma mark Convenience

/**
 * Creates and returns a PMRatchetJoint object initialized to bind two given rigid 
 * bodies with given phase and ratchet angles. 
 */
+ (PMRatchetJoint *)ratchetJointWithBodyA:(PMBody *)aBody bodyB:(PMBody *)otherBody phase:(PMFloat)phase ratchet:(PMFloat)ratchet {
	return [[[PMRatchetJoint alloc] initWithBodyA:aBody
											bodyB:otherBody 
											phase:phase 
										  ratchet:ratchet] autorelease];
}


#pragma mark -
#pragma mark Getters

/**
 * Returns the initial angle offset between the receiver's bound rigid bodies.
 * This angle is used to determine where the ratchet angles are placed.
 */
- (PMFloat)phase {
	return cpRatchetJointGetPhase(constraint);
}

/**
 * Returns the angle between each of the receivers ratchet teeth, or "clicks".
 */
- (PMFloat)ratchet {
	return cpRatchetJointGetRatchet(constraint);
}

/**
 * Returns the current angle between the two bodies bound by the receiver, relative
 * to the receiver's phase angle.
 */
- (PMFloat)angle {
	return cpRatchetJointGetAngle(constraint);
}


#pragma mark -
#pragma mark Setters

/**
 * Sets the initial angle offset between the receiver's bound rigid bodies to 
 * a given value, in radians.
 */
- (void)setPhase:(PMFloat)phase {
	return cpRatchetJointSetPhase(constraint, phase);
}

/**
 * Sets the angle between each of the receiver's ratchet teeth, or "clicks" to a
 * given value, in radian.
 */
- (void)setRatchet:(PMFloat)ratchet {
	return cpRatchetJointSetRatchet(constraint, ratchet);
}

/**
 * Sets the current angle between the two bodies bound by the receiver to a given
 * value, in radians, relative to the receiver's phase angle.
 */
- (void)setAngle:(PMFloat)angle {
	return cpRatchetJointSetAngle(constraint, angle);
}

@end
